using System;
using SharedKernel.Domain;
using SharedKernel.Domain.Events;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace ProductService.Domain.Models
{
    /// <summary>
    /// 商品实体
    /// </summary>
    public class Product : CreateUpdateDeleteEntity<Guid>
    {

        private readonly List<IDomainEvent> _domainEvents = new();

        /// <summary>
        /// 领域事件集合
        /// </summary>
        public IReadOnlyCollection<IDomainEvent> DomainEvents => new ReadOnlyCollection<IDomainEvent>(_domainEvents);

        /// <summary>
        /// 清除领域事件
        /// </summary>
        public void ClearDomainEvents()
        {
            _domainEvents.Clear();
        } 
        /// <summary>
        /// 商品名称
        /// </summary>
        public string Name { get; private set; }

        /// <summary>
        /// 商品描述
        /// </summary>
        public string Description { get; private set; }

        /// <summary>
        /// 商品价格
        /// </summary>
        public decimal Price { get; private set; }

        /// <summary>
        /// 商品库存
        /// </summary>
        public int Stock { get; private set; }

        /// <summary>
        /// 商品分类
        /// </summary>
        public string Category { get; private set; }

        /// <summary>
        /// 公共无参数构造函数，用于ORM框架
        /// </summary>
        public Product() : base(Guid.NewGuid()) { }

        /// <summary>
        /// 创建商品
        /// </summary>
        /// <param name="name">商品名称</param>
        /// <param name="description">商品描述</param>
        /// <param name="price">商品价格</param>
        /// <param name="stock">商品库存</param>
        /// <param name="category">商品分类</param>
        /// <returns>商品实体</returns>
        public static Product Create(string name, string description, decimal price, int stock, string category)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentNullException(nameof(name), "商品名称不能为空");

            if (price < 0)
                throw new ArgumentException("商品价格不能为负数", nameof(price));

            if (stock < 0)
                throw new ArgumentException("商品库存不能为负数", nameof(stock));

            return new Product
            {
                Name = name,
                Description = description,
                Price = price,
                Stock = stock,
                Category = category
            };
        }

        /// <summary>
        /// 更新商品信息
        /// </summary>
        /// <param name="name">商品名称</param>
        /// <param name="description">商品描述</param>
        /// <param name="price">商品价格</param>
        /// <param name="category">商品分类</param>
        public void Update(string name = null, string description = null, decimal? price = null, string category = null)
        {
            if (!string.IsNullOrWhiteSpace(name))
                Name = name;

            if (!string.IsNullOrWhiteSpace(description))
                Description = description;

            if (price.HasValue && price.Value >= 0)
                Price = price.Value;

            if (!string.IsNullOrWhiteSpace(category))
                Category = category;

            //MarkAsUpdated();
        }

        /// <summary>
        /// 减少库存
        /// </summary>
        /// <param name="quantity">减少数量</param>
        public void ReduceStock(int quantity)
        {
            if (quantity <= 0)
                throw new ArgumentException("减少数量必须大于0", nameof(quantity));

            if (Stock < quantity)
                throw new InvalidOperationException("库存不足");

            Stock -= quantity;
            //MarkAsUpdated();
        }

        /// <summary>
        /// 增加库存
        /// </summary>
        /// <param name="quantity">增加数量</param>
        public void IncreaseStock(int quantity)
        {
            if (quantity <= 0)
                throw new ArgumentException("增加数量必须大于0", nameof(quantity));

            Stock += quantity;
            //MarkAsUpdated();
        }

        /// <summary>
        /// 添加领域事件
        /// </summary>
        /// <param name="domainEvent">领域事件</param>
        protected void AddDomainEvent(IDomainEvent domainEvent)
        {
            _domainEvents.Add(domainEvent);
        }
    }
}